#include <QtTest>
#include <QtWebKit>
#include "oauth.h"
#include "plurkapi.h"
#include "plurkauthview.h"

class PlurkTest : public QObject
{
  Q_OBJECT;

public:
  PlurkTest();

private:
  Q_SLOT void testOAuthHmac();
  Q_SLOT void testOAuthSignature();
  Q_SLOT void testOAuthSignatureParameters();
  Q_SLOT void testOAuthSignatureAuto();
  Q_SLOT void testPlurkToken();
  Q_SLOT void testPlurkAPIOAuth();
  Q_SLOT void testPlurkAPI();
  Q_SLOT void testStoredOAuth();

private:
  QString consumerKey;
  QString consumerSecret;
  QString appKey;
  QString appSecret;
};

PlurkTest::PlurkTest()
{
}

void PlurkTest::testOAuthHmac()
{
  OAuth oauth;

  QCOMPARE(oauth.hmacSha1("uu0yrNkFTIa98QJnZMLt5qdWLrsqjvM5&", "POST&http%3A%2F%2Fwww.plurk.com%2FOAuth%2Frequest_token&oauth_consumer_key%3DB2lxkOMDnfCH%26oauth_nonce%3D66516172%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1311412258%26oauth_version%3D1.0"),
           QUrl::fromPercentEncoding("HabeMJlOkeP3yN%2FtQFPAkg%2Bs%2F8o%3D"));
}

void PlurkTest::testOAuthSignature()
{
  OAuth oauth;

  QCOMPARE(oauth.signature("POST", "http://www.plurk.com/OAuth/request_token",
                 "oauth_consumer_key=B2lxkOMDnfCH&oauth_nonce=75276476&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1311401189&oauth_version=1.0",
                           "uu0yrNkFTIa98QJnZMLt5qdWLrsqjvM5"),
           QString("YrT9xN025rBLabS0nNNJ7snKVE8="));
}

void PlurkTest::testOAuthSignatureParameters()
{
  OAuth oauth;
  QMap<QString, QString> params;

  params["oauth_consumer_key"]     = "B2lxkOMDnfCH";
  params["oauth_nonce"]            = "75276476";
  params["oauth_signature_method"] = "HMAC-SHA1";
  params["oauth_timestamp"]        = "1311401189";
  params["oauth_version"]          = "1.0";

  QCOMPARE(oauth.signature("POST", "http://www.plurk.com/OAuth/request_token", params, "uu0yrNkFTIa98QJnZMLt5qdWLrsqjvM5"),
           QString("YrT9xN025rBLabS0nNNJ7snKVE8="));
}

void PlurkTest::testOAuthSignatureAuto()
{
  OAuth oauth;

  oauth.setConsumerKey("B2lxkOMDnfCH");
  oauth.setConsumerSecret("uu0yrNkFTIa98QJnZMLt5qdWLrsqjvM5");
  QCOMPARE(oauth.generateSignature("POST", "http://www.plurk.com/OAuth/request_token", "75276476", "1311401189"),
           QString("YrT9xN025rBLabS0nNNJ7snKVE8="));
}

void PlurkTest::testPlurkToken()
{
  int count = 0;
  OAuth oauth;

  QSignalSpy spy(&oauth, SIGNAL(performAuth(const QString &)));
  oauth.setConsumerKey("B2lxkOMDnfCH");
  oauth.setConsumerSecret("uu0yrNkFTIa98QJnZMLt5qdWLrsqjvM5");

  oauth.requestToken("POST", "http://www.plurk.com/OAuth/request_token");
  while (count < 150) {
    count++;
    QTest::qWait(100);
    if (spy.count() > 0) break;
  }

  QVERIFY(spy.count() == 1);

  QWebView view;
  QSignalSpy urlChange(&view, SIGNAL(urlChanged(const QUrl &)));
  view.load(QUrl("http://www.plurk.com//m/authorize?oauth_token=" + oauth.tokenKey()));
  view.showMaximized();
  /*
  view.setMinimumSize(640, 480);
  view.setMaximumSize(640, 480);
  view.setGeometry(0, 0, 640, 480);
  view.show();
  */

  QSignalSpy load(&view, SIGNAL(loadFinished(bool)));
  while (1) {
    if (urlChange.count() > 0) {
      QString str = urlChange.takeFirst().at(0).toString();
      if (str == "http://www.plurk.com/OAuth/authorizeDone") {
        break;
      }
    }
    QTest::qWait(100);
  }

  QString _verify = "";
  while (1) {
    if (load.count() > 0) {
        QString str = view.page()->currentFrame()->toHtml();
        QRegExp rx("( <b>)([0-9]+)(</b><br>)");
        int pos = 0;
        while ((pos = rx.indexIn(str, pos)) != -1) {
          _verify = rx.cap(2);
          pos += rx.matchedLength();
        }
        if (_verify.length() > 0)
          break;
    }
    QTest::qWait(100);
  }

  view.close();

  oauth.setTokenVerifier(_verify);
  oauth.requestAccessToken("POST", "http://www.plurk.com/OAuth/access_token");

  QSignalSpy finishAccess(&oauth, SIGNAL(finishAccess()));
  while (1) {
    if (finishAccess.count() > 0) {
        break;
    }
    QTest::qWait(100);
  }

  QVERIFY(finishAccess.count() == 1);

  oauth.requestApplication("GET", "http://www.plurk.com/APP/Polling/getUnreadCount");
  QSignalSpy app(&oauth, SIGNAL(appRequestFinish(const QUrl &, const QString &)));
  while (1) {
    if (app.count() > 0) {
      qDebug() << " APP DATA " << app.takeFirst().at(1).toString();
      break;
    }
    QTest::qWait(100);
  }
  QTest::qWait(100);

  consumerKey = oauth.consumerKey();
  consumerSecret = oauth.consumerSecret();
  appKey = oauth.appKey();
  appSecret = oauth.appSecret();
  QSettings settings("cookie.ini", QSettings::IniFormat);

  settings.setValue("ConsumerKey",    consumerKey);
  settings.setValue("ConsumerSecret", consumerSecret);
  settings.setValue("AppKey",         appKey);
  settings.setValue("AppSecret",      appSecret);
}

void PlurkTest::testPlurkAPIOAuth()
{
  QUrl url;
  int count;
  PlurkAPI plurkAPI;
  PlurkAuthView plurkAuthView;

  plurkAPI.setConsumerKey("B2lxkOMDnfCH");
  plurkAPI.setConsumerSecret("uu0yrNkFTIa98QJnZMLt5qdWLrsqjvM5");
  plurkAPI.initRequestToken();

  QSignalSpy openAuthUrl(&plurkAPI, SIGNAL(openAuthUrl(const QUrl&)));
  count = 0;
  while (count < 100) {
    if (openAuthUrl.count() > 0) {
      url = openAuthUrl.takeFirst().at(0).toUrl();
      break;
    }
    count++;
    QTest::qWait(100);
  }

  QVERIFY(url.toString().startsWith("http://www.plurk.com//m/authorize?oauth_token="));

  plurkAuthView.openAuth(url);
  plurkAuthView.showMaximized();
  QSignalSpy authDone(&plurkAuthView, SIGNAL(authDone(bool, const QString &)));
  while (1) {
    if (authDone.count() > 0) {
      break;
    }
    QTest::qWait(100);
  }

  QVERIFY(authDone.at(0).at(0).toBool());
  QVERIFY(authDone.at(0).at(1).toString().length() > 0);

  plurkAuthView.close();

  QSignalSpy finishOAuth(&plurkAPI, SIGNAL(finishOAuth()));
  plurkAPI.startAccessToken(authDone.at(0).at(1).toString());

  count = 0;
  while (count < 100) {
    if (finishOAuth.count() > 0) {
      break;
    }
    count++;
    QTest::qWait(100);
  }

  QVERIFY(finishOAuth.count() == 1);

  consumerKey = plurkAPI.consumerKey();
  consumerSecret = plurkAPI.consumerSecret();
  appKey = plurkAPI.appKey();
  appSecret = plurkAPI.appSecret();
  QSettings settings("cookie.ini", QSettings::IniFormat);

  settings.setValue("ConsumerKey",    consumerKey);
  settings.setValue("ConsumerSecret", consumerSecret);
  settings.setValue("AppKey",         appKey);
  settings.setValue("AppSecret",      appSecret);
}

void PlurkTest::testPlurkAPI()
{
  PlurkAPI plurkAPI;
  QSettings settings("cookie.ini", QSettings::IniFormat);

  consumerKey    = settings.value("ConsumerKey").toString();
  consumerSecret = settings.value("ConsumerSecret").toString();
  appKey         = settings.value("AppKey").toString();
  appSecret      = settings.value("AppSecret").toString();
  plurkAPI.setConsumerKey(consumerKey);
  plurkAPI.setConsumerSecret(consumerSecret);
  plurkAPI.setAppKey(appKey);
  plurkAPI.setAppSecret(appSecret);


}

void PlurkTest::testStoredOAuth()
{
  QScriptEngine engine;
  OAuth oauth;
  QString data = "";

  QSettings settings("cookie.ini", QSettings::IniFormat);

  consumerKey    = settings.value("ConsumerKey").toString();
  consumerSecret = settings.value("ConsumerSecret").toString();
  appKey         = settings.value("AppKey").toString();
  appSecret      = settings.value("AppSecret").toString();
  oauth.setConsumerKey(consumerKey);
  oauth.setConsumerSecret(consumerSecret);
  oauth.setAppKey(appKey);
  oauth.setAppSecret(appSecret);

  oauth.requestApplication("GET", "http://www.plurk.com/APP/Polling/getUnreadCount");
  QSignalSpy app(&oauth, SIGNAL(appRequestFinish(const QUrl &, const QString &)));
  while (1) {
    if (app.count() > 0) {
      data = app.takeFirst().at(1).toString();
      break;
    }
    QTest::qWait(100);
  }

  QVERIFY(data.length() > 0);
  QScriptValue value = engine.evaluate('(' + data + ')');

  QVERIFY(value.toVariant().type() == QVariant::Map);

  QMap<QString, QVariant> map = value.toVariant().toMap();
  QVERIFY(map.contains("all"));
  QVERIFY(map.contains("private"));
  QVERIFY(map.contains("responded"));

  QTest::qWait(100);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
 
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
 
    PlurkTest tc;
    return QTest::qExec(&tc, argc, argv);
}
 
#include "plurktest.moc" 
